package at.fhooe.mc.control.automation;

/*************************************************************************
 *	Single Elevator Control Algorithm
 *  A simple control algorithm for a single elevator
 *
 *  SingleElevatorControlAlgorithm.java
 *************************************************************************/
import java.util.ArrayList;
import at.fhooe.mc.data.DirectionType;
import at.fhooe.mc.data.ElevatorData;
import at.fhooe.mc.data.FloorData;
import at.fhooe.mc.data.SystemData;

public class SingleElevatorControlAlgorithm implements IAutoAlgorithm
{
	// ===========================================================================
	@Override
	public void init(SystemData data)
	{
		// do nothing
	}

	// ===========================================================================
	@Override
	public void newValuesAvailable(SystemData data, IAutomationControl control)
	{
		ElevatorData elevator = data.getElevators().get(0);
		// buttons inside the elevator UP
		Integer nextUpperFloor = getNextUpperFloor(elevator.getElevatorButton(), data.getFloors(), elevator.getElevatorFloor());

		// buttons inside the elevator DOWN
		Integer  firstDownerFloor = getFirstDownerFloor(elevator.getElevatorButton(), data.getFloors(), elevator.getElevatorFloor());
		Integer nextDownerFloor = getNextDownerFloor(elevator.getElevatorButton(), data.getFloors(), elevator.getElevatorFloor());

		if (elevator.getCommittedDirection() == DirectionType.UP || elevator.getCommittedDirection() == DirectionType.UNCOMMITTED)
		{
			if (nextUpperFloor != null)
				control.autoControl(0, nextUpperFloor);
			else if (firstDownerFloor != null)
				control.autoControl(0, firstDownerFloor);  // may go up to pick up people whom wants to go down
			else if (nextDownerFloor != null)
				control.autoControl(0, nextDownerFloor);
			else
				control.autoControl(0, 0); // send the elevator to the ground
											// floor on idle conditions
			return;
		}
		if (elevator.getCommittedDirection() == DirectionType.DOWN)
		{
			if (nextDownerFloor != null)
				control.autoControl(0, nextDownerFloor);
			else if (nextUpperFloor != null)
				control.autoControl(0, nextUpperFloor);
			else
				control.autoControl(0, 0); // send the elevator to the ground
											// floor on idle conditions
			return;
		}

	}

	// ===========================================================================
	/**
	 *
	 * @param elevatorButtons
	 *            : Array of booleans modelling the buttons pressed inside of
	 *            the elevator
	 * @param floors
	 *            : ArrayListy of FLorData modelling the floors of the building,
	 *            form it the pressed buttons on each floor
	 * @param currentFloor
	 *            : current floor
	 * @return the next upper floor from the current one with a request, even
	 *         from inside of the elevator or in the building's floors
	 */
	private Integer getNextUpperFloor(boolean[] elevatorButtons, ArrayList<FloorData> floors, int currentFloor)
	{
		Integer nextUpperFloor = null;
		int i = currentFloor + 1;
		while (i < elevatorButtons.length)
		{
			if (elevatorButtons[i] == true || floors.get(i).isFloorButtonUp())
			{
				nextUpperFloor = i;
				break;
			}
			i++;
		}
		return nextUpperFloor;
	}

	// ===========================================================================
	/**
	 *
	 * @param elevatorButtons
	 *            : Array of booleans modelling the buttons pressed inside of
	 *            the elevator
	 * @param floors
	 *            : ArrayListy of FLorData modelling the floors of the building,
	 *            form it the pressed buttons on each floor
	 * @param currentFloor
	 *            : current floor
	 * @return the next downer floor from the current one with a request, even
	 *         from inside of the elevator or in one of the building's floors
	 */
	private Integer getNextDownerFloor(boolean[] elevatorButtons, ArrayList<FloorData> floors, int currentFloor)
	{
		Integer nextDownerFloor = null;
		int i = currentFloor - 1;
		while (i >= 0)
		{
			if (elevatorButtons[i] == true || floors.get(i).isFloorButtonDown())
			{
				nextDownerFloor = i;
				break;
			}
			i--;
		}
		return nextDownerFloor;
	}
	// ===========================================================================
	/**
	 *	Finds the first floor from the top of the building which has a request for going down
	 *
	 * @param elevatorButtons
	 *            : Array of booleans modelling the buttons pressed inside of
	 *            the elevator
	 * @param floors
	 *            : ArrayListy of FLorData modelling the floors of the building,
	 *            form it the pressed buttons on each floor
	 * @param currentFloor
	 *            : current floor
	 * @return the next downer floor from the current one with a request, even
	 *         from inside of the elevator or in one of the building's floors
	 */
	private Integer getFirstDownerFloor(boolean[] elevatorButtons, ArrayList<FloorData> floors, int currentFloor)
	{
		Integer nextDownerFloor = null;
		int i = elevatorButtons.length-1;
		while (i >= 0)
		{
			if (elevatorButtons[i] == true || floors.get(i).isFloorButtonDown())
			{
				nextDownerFloor = i;
				break;
			}
			i--;
		}
		return nextDownerFloor;
	}

	// ===========================================================================
}
